package com.unswift.window.factory;

import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.text.AttributeSet;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;

import com.unswift.QuickApplication;
import com.unswift.utils.FileUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.window.editor.Editor;
import com.unswift.window.editor.EditorDocument;
import com.unswift.window.undo.UndoManager;

public final class EditorFactory {
	
	/**
	 * 规定Tab键的宽度
	 */
	public static void setTabWidth(Editor editor) {
		int tabUnit=28;
		TabStop[] tabs = new TabStop[100];
		for (int i = 0; i < 100; i++) {
			tabs[i] = new TabStop((i+1)*tabUnit, TabStop.ALIGN_LEFT, TabStop.LEAD_NONE); 
		}
		TabSet tabset = new TabSet(tabs);
		StyleContext sc = StyleContext.getDefaultStyleContext();
		AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.TabSet, tabset);
		editor.setParagraphAttributes(aset, false);
	}
	
	public static void replaceText(Editor editor, String replaceText, boolean nextLine){
		try {
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			replaceText(editor, start, end, replaceText, nextLine, true);
		} catch (Exception e) {
			e.printStackTrace();
			MessageFactory.error(QuickApplication.getWindow(), "异常："+e.getMessage());
		}
	}
	
	public static void replaceText(Editor editor, int start, int end, String replaceText, boolean nextLine, boolean showQuickTipsFlag){
		EditorDocument document=(EditorDocument)editor.getDocument();
		try {
			if(start==end){
				int length=document.getLength();
				document.remove(0, length);
				document.setNewAction(false);
				document.insertString(0, replaceText, new SimpleAttributeSet());
				document.setNewAction(true);
				start=document.getLength();
			}else{
				if(showQuickTipsFlag){
					document.setShowQuickTips(false);
				}
				document.remove(start, end-start);
				replaceText=(nextLine?FileUtils.nextLine():"")+replaceText;
				if(showQuickTipsFlag){
					document.setShowQuickTips(true);
				}
				document.setNewAction(false);
				document.insertString(start, replaceText, new SimpleAttributeSet());
				document.setNewAction(true);
				start+=replaceText.length();
			}
			editor.setSelectionStart(start);
			editor.setSelectionEnd(start);
		} catch (Exception e) {
			e.printStackTrace();
			MessageFactory.error(QuickApplication.getWindow(), "异常："+e.getMessage());
		} finally{
			if(showQuickTipsFlag){
				document.setShowQuickTips(true);
			}
		}
	}
	
	public static void insertText(Editor editor, String subText, boolean nextLine){
		EditorDocument document=(EditorDocument)editor.getDocument();
		try {
			document.setShowQuickTips(false);
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			int length=document.getLength();
			subText=(start!=0?(nextLine?FileUtils.nextLine():""):"")+subText+(end<length?(nextLine?FileUtils.nextLine():""):"");
			if(start!=end){
				document.remove(start, end-start);
				document.setNewAction(false);
			}
			document.setShowQuickTips(true);
			document.insertString(start, subText, new SimpleAttributeSet());
			start+=subText.length();
			editor.setSelectionStart(start);
			editor.setSelectionEnd(start);
		} catch (Exception e) {
			e.printStackTrace();
			MessageFactory.error(QuickApplication.getWindow(), "插入Sql异常："+e.getMessage());
		} finally {
			document.setShowQuickTips(true);
			document.setNewAction(true);
		}
	}
	
	public static void appendText(Editor editor, String subText, boolean nextLine, boolean maxHeightScroll){
		try {
			subText=subText+(nextLine?FileUtils.nextLine():"");
			editor.getDocument().insertString(editor.getDocument().getLength(), subText, new SimpleAttributeSet());
			if(maxHeightScroll){
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						JScrollPane scroll = (JScrollPane)editor.getParent().getParent();
						JScrollBar verticalScrollBar = scroll.getVerticalScrollBar();
						int maxScrollHeight=verticalScrollBar.getMaximum();
						if(maxScrollHeight>0){
							verticalScrollBar.setValue(maxScrollHeight);
						}
					}
				});
			}
		} catch (Exception e) {
			e.printStackTrace();
			MessageFactory.error(QuickApplication.getWindow(), "插入Sql异常："+e.getMessage());
		}
	}
	
	public static void beforeOperator(Editor editor) {
		UndoManager undoManager=editor.getAttribute(Editor.ATTRIBUTE_EDITOR_UNDO_MANAGER);
		if(undoManager.canUndo()){
			undoManager.undo();
		}
	}
	
	public static void afterOperator(Editor editor) {
		UndoManager undoManager=editor.getAttribute(Editor.ATTRIBUTE_EDITOR_UNDO_MANAGER);
		if(undoManager.canRedo()){
			undoManager.redo();
		}
	}
	
	public static void deleteEditorLine(Editor editor) {
		try {
			Document document = editor.getDocument();
			int length;
			Element element = document.getDefaultRootElement(), row;
			int count = element.getElementCount(), rowStart, rowEnd;
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			boolean delete=false;
			for (int i = count-1; i >= 0; i--) {
				row = element.getElement(i);
				rowStart = row.getStartOffset();
				rowEnd = row.getEndOffset();
				if((i==count-1 && end>=rowEnd) || (end>=rowStart && end<rowEnd)){
					delete=true;
				}
				if(delete){
					length=document.getLength();
					int realEnd=rowEnd>length?length:rowEnd;
					if(i==count-1 && i!=0){
						int realStart=rowStart-1;
						document.remove(realStart, realEnd-realStart);
					}else{
						document.remove(rowStart, realEnd-rowStart);
					}
				}
				if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
					delete=false;
				}
			}
		} catch (Exception e2) {
			e2.printStackTrace();
		}
	}
	
	public static void copyLineUp(Editor editor){
		try {
			Document document = editor.getDocument();
			Element element = document.getDefaultRootElement(), row;
			int count = element.getElementCount(), rowStart, rowEnd, copyStart=0;
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			for (int i = 0; i < count; i++) {
				row = element.getElement(i);
				rowStart = row.getStartOffset();
				rowEnd = row.getEndOffset();
				if(start==end){
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						String copyText=document.getText(rowStart, rowEnd-rowStart);
						document.insertString(rowStart, copyText, new SimpleAttributeSet());
						editor.setSelectionStart(rowStart);
						editor.setSelectionEnd(rowStart);
						break;
					}
				}else{
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						copyStart=start;
					}
					if((i==count-1 && end>=rowEnd) || (end>=rowStart && end<rowEnd)){
						String copyText=document.getText(copyStart, rowEnd-copyStart);
						document.insertString(copyStart, copyText, new SimpleAttributeSet());
						editor.setSelectionStart(copyStart);
						editor.setSelectionEnd(copyStart);
						break;
					}
				}
			}
		} catch (Exception e2) {
			e2.printStackTrace();
		}
	}
	
	public static void copyLineDown(Editor editor){
		try {
			Document document = editor.getDocument();
			Element element = document.getDefaultRootElement(), row;
			int count = element.getElementCount(), rowStart, rowEnd, copyStart=0;
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			for (int i = 0; i < count; i++) {
				row = element.getElement(i);
				rowStart = row.getStartOffset();
				rowEnd = row.getEndOffset();
				if(start==end){
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						String copyText=document.getText(rowStart, rowEnd-rowStart);
						document.insertString(rowEnd, copyText, new SimpleAttributeSet());
						rowEnd+=rowEnd-rowStart;
						editor.setSelectionStart(rowEnd);
						editor.setSelectionEnd(rowEnd);
						break;
					}
				}else{
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						copyStart=start;
					}
					if((i==count-1 && end>=rowEnd) || (end>=rowStart && end<rowEnd)){
						String copyText=document.getText(copyStart, rowEnd-copyStart);
						document.insertString(rowEnd, copyText, new SimpleAttributeSet());
						rowEnd+=rowEnd-rowStart;
						editor.setSelectionStart(rowEnd);
						editor.setSelectionEnd(rowEnd);
						break;
					}
				}
			}
		} catch (Exception e2) {
			e2.printStackTrace();
		}
	}
	
	public static void moveLineUp(Editor editor){
		try {
			EditorDocument document = (EditorDocument)editor.getDocument();
			int length=document.getLength();
			Element element = document.getDefaultRootElement(), row;
			int count = element.getElementCount(), rowStart, rowEnd, copyEnd=0;
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			String copyText=null;
			for (int i = count-1; i >= 0; i--) {
				row = element.getElement(i);
				rowStart = row.getStartOffset();
				rowEnd = row.getEndOffset();
				if(ObjectUtils.isNotNull(copyText)){
					document.setNewAction(false);
					document.insertString(rowStart, copyText, new SimpleAttributeSet());
					document.setNewAction(true);
					editor.setSelectionStart(rowStart);
					editor.setSelectionEnd(rowStart);
					break;
				}
				if(start==end){
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						copyText=document.getText(rowStart, rowEnd-rowStart);
						rowEnd=rowEnd>length?length:rowEnd;
						if(i>0){
							document.remove(rowStart, rowEnd-rowStart);
						}
					}
				}else{
					if((i==count-1 && end>=rowEnd) || (end>=rowStart && end<rowEnd)){
						copyEnd=end;
					}
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						copyText=document.getText(rowStart, copyEnd-rowStart);
						copyEnd=copyEnd>length?length:copyEnd;
						if(i>0){
							document.remove(rowStart, copyEnd-rowStart);
						}
					}
				}
			}
		} catch (Exception e2) {
			e2.printStackTrace();
		}
	}
	
	public static void moveLineDown(Editor editor){
		try {
			EditorDocument document = (EditorDocument)editor.getDocument();
			int length=document.getLength();
			Element element = document.getDefaultRootElement(), row;
			int count = element.getElementCount(), rowStart, rowEnd, deleteStart=-1, deleteLength=-1, copyStart=0;
			int start=editor.getSelectionStart();
			int end=editor.getSelectionEnd();
			String copyText=null;
			for (int i = 0; i < count; i++) {
				row = element.getElement(i);
				rowStart = row.getStartOffset();
				rowEnd = row.getEndOffset();
				if(ObjectUtils.isNotNull(copyText)){
					document.setNewAction(false);
					document.insertString(rowEnd, copyText, new SimpleAttributeSet());
					document.setNewAction(true);
					editor.setSelectionStart(rowEnd);
					editor.setSelectionEnd(rowEnd);
					break;
				}
				if(start==end){
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						copyText=document.getText(rowStart, rowEnd-rowStart);
						rowEnd=rowEnd>length?length:rowEnd;
						if(i!=count-1){
							deleteStart=rowStart;
							deleteLength=rowEnd-rowStart;
						}
					}
				}else{
					if((i==count-1 && start>=rowEnd) || (start>=rowStart && start<rowEnd)){
						copyStart=start;
					}
					if((i==count-1 && end>=rowEnd) || (end>=rowStart && end<rowEnd)){
						copyText=document.getText(copyStart, rowEnd-rowStart);
						rowEnd=rowEnd>length?length:rowEnd;
						if(i!=count-1){
							deleteStart=copyStart;
							deleteLength=rowEnd-rowStart;
						}
					}
				}
			}
			if(deleteStart!=-1 && deleteLength!=-1){
				document.remove(deleteStart, deleteLength);
			}
		} catch (Exception e2) {
			e2.printStackTrace();
		}
	}
	
	public static void find(Editor editor, String findWord, boolean ignore){
		EditorDocument document=(EditorDocument)editor.getDocument();
		document.find(findWord, ignore);
	}
	
	public static void replace(Editor editor, String findWord, String replaceWord, boolean ignore){
		EditorDocument document=(EditorDocument)editor.getDocument();
		document.replace(findWord, replaceWord, ignore);
	}
}
